package back.wiring

import javax.inject.Provider

import play.api.ApplicationLoader.Context
import play.api._
import com.softwaremill.macwire._
import com.softwaremill.macwire.akkasupport._
import com.softwaremill.tagging._
import _root_.utils._
import play.api.http.DefaultHttpErrorHandler
import play.api.libs.ws.WSClient
import play.api.mvc._
import play.api.routing.Router
import play.filters.HttpFiltersComponents
import play.filters.csrf.CSRFFilter
import wiring.BasicSecurityWiringImpl
import _root_.controllers.AssetsConfiguration
import akka.actor.ActorRef
import archer.back.controllers._
import org.xarcher.emiya.utils._
import play.api.cache.ehcache.EhCacheComponents

class BackAppComponents(
  context: Context,
  commonDB: CommonDB,
  wSClient: WSClient,
  assetsConfiguration: AssetsConfiguration)
  extends BuiltInComponentsFromContext(context)
  with HttpFiltersComponents
  with EhCacheComponents {
  self =>

  private implicit val ec = executionContext

  private lazy val CustomAssets: CustomAssets = {
    lazy val CustomAssetsMetadata = wire[CustomAssetsMetadata]
    wire[CustomAssets]
  }
  /*
   * Assets 模块配置结束
   */

  /*
   * 错误响应模块配置开始
   */
  private lazy val OptionalSourceMapper: OptionalSourceMapper =
    new OptionalSourceMapper(context.sourceMapper)
  private lazy val DefaultHttpErrorHandler: DefaultHttpErrorHandler =
    wire[DefaultHttpErrorHandler]
  private lazy val routesProvider: Provider[Router] = new Provider[Router] {
    override def get() = router
  }
  /*
   * 错误响应模块配置结束
   */

  private lazy val basicWiringImpl: BasicSecurityWiringImpl =
    wire[BasicSecurityWiringImpl]

  private def timeLimitedActor: ActorRef @@ TimeLimitedActor =
    wireAnonymousActor[TimeLimitedActor].taggedWith[TimeLimitedActor]
  private def limitedActor: ActorRef @@ LimitedActor =
    wireAnonymousActor[LimitedActor].taggedWith[LimitedActor]

  private lazy val timeLimitedActorGen: () => ActorRef @@ TimeLimitedActor =
    () => timeLimitedActor
  private lazy val limitedActorGen: () => ActorRef @@ LimitedActor = () =>
    limitedActor

  private lazy val futureTimeLimitedGen: FutureTimeLimitedGen =
    wire[FutureTimeLimitedGen]
  private lazy val futureLimitedGen: FutureLimitedGen = wire[FutureLimitedGen]

  /*private lazy val crawlService: CrawlService = {
    val cache = cacheApi("crawl-url")
    wire[CrawlService]
  }*/
  //private lazy val urlService: UrlService = wire[UrlService]
  private lazy val planService: PlanService = wire[PlanService]
  private lazy val searchService: SearchService = wire[SearchService]
  private lazy val updateService: UpdateService = wire[UpdateService]
  private lazy val nodeInfoService: NodeInfoService = wire[NodeInfoService]
  private lazy val crawlResultService: CrawlResultService =
    wire[CrawlResultService]
  private lazy val elasticService: ElasticService = {
    val cache = cacheApi("url-cache")
    wire[ElasticService]
  }

  private lazy val planController: PlanController = wire[PlanController]
  private lazy val urlsController: UrlsController = wire[UrlsController]
  private lazy val crawlResultController: CrawlResultController =
    wire[CrawlResultController]
  private lazy val updateController: UpdateController = wire[UpdateController]
  private lazy val nodeInfoController: NodeInfoController =
    wire[NodeInfoController]
  private lazy val elasticSearch: ElasticSearch = wire[ElasticSearch]
  private lazy val wsClientE4SRequestClient: WsClientE4SRequestClient =
    wire[WsClientE4SRequestClient]

  private lazy val embeddedServer = wire[EmbeddedServer]

  override def httpFilters: Seq[EssentialFilter] = {
    super.httpFilters.filterNot(_.getClass == classOf[CSRFFilter])
  }

  // Router
  override lazy val router: back.Routes = {
    val routePrefix: String = "/"
    wire[back.Routes]
  }

}
